Подготовка стенда и модель экспоненциального роста
2026-02-20
---
## Докладчик
:::::::::::::: {.columns align=center}
::: {.column width="70%"}
* Алина Тарасова
* студент
* Российский университет дружбы народов им. П. Лумумбы
* [destinyshesaid@yandex.ru](mailto:destinyshesaid@yandex.ru)
* GitHub: @aatarasovaa
:::
::: {.column width="30%"}

:::
::::::::::::::
---
# Вводная часть
## Актуальность
- Имитационное моделирование — важный инструмент исследования сложных систем
- Необходимость воспроизводимости научных результатов
- Современные требования к организации вычислительных экспериментов
- Потребность в интеграции кода, данных и отчётов
## Объект и предмет исследования
- **Объект:** Процесс имитационного моделирования
- **Предмет:**
- Модель экспоненциального роста
- Инструменты для организации научных проектов
- Методы литературного программирования
## Цели и задачи
### Цель работы
Исследование модели экспоненциального роста $\frac{du}{dt} = \alpha u$ с использованием современных инструментов организации научных проектов
### Задачи
1. Настроить рабочее окружение (Git, SSH, PGP, Git-flow)
2. Освоить методологию литературного программирования
3. Изучить фреймворк DrWatson.jl
4. Реализовать базовую модель экспоненциального роста
5. Провести параметрическое исследование
6. Создать отчёт и презентацию с использованием Quarto
---
# Настройка рабочего окружения
## Система контроля версий Git
### Базовая конфигурация
```bash
# Настройка пользователя
git config --global user.name "Алина Тарасова"
git config --global user.email "destinyshesaid@yandex.ru"
# Настройка ветки по умолчанию
git config --global init.defaultBranch master
# Настройка переносов строк
git config --global core.autocrlf input
git config --global core.safecrlf warn
gpg --full-generate-key # RSA 4096 бит
gpg --list-secret-keys --keyid-format LONG
gpg --armor --export D17BA68B48151B6E # экспорт ключаPGP ключ на GitHub
# Установка git-flow
sudo apt install git-flow -y
# Установка pnpm
curl -fsSL https://get.pnpm.io/install.sh | sh -
source ~/.bashrc
# Установка инструментов для коммитов
pnpm add -g commitizen cz-customizable standard-version~/work/study/2026-1/
└── 2026-1==study--simulation-modeling/
└── 2026-1--study--simulation-modeling/
├── labs/
│ └── lab01/
│ └── project/
│ ├── src/ # исходный код
│ ├── scripts/ # исполняемые скрипты
│ ├── data/ # данные
│ ├── plots/ # графики
│ └── notebooks/ # Jupyter notebooks
├── report/ # отчёт
└── presentation/ # презентацияpackages = [
"DrWatson", # организация проектов
"DifferentialEquations", # решение ОДУ
"Plots", # визуализация
"DataFrames", # работа с данными
"Literate", # литературное программирование
"IJulia", # интеграция с Jupyter
"BenchmarkTools", # оценка производительности
"Quarto" # создание отчётов
]
Pkg.add(packages) # время установки: ~30 минут#, интерпретируются как Markdowntangle.jl [стр. 74-75]Чистый скрипт: scripts/01_exponential_growth/01_exponential_growth.jl
Quarto: markdown/01_exponential_growth/01_exponential_growth.qmd
Notebook: notebooks/01_exponential_growth/01_exponential_growth.ipynb
\[ \frac{du}{dt} = \alpha u, \quad u(0) = u_0 \]
\[ u(t) = u_0 e^{\alpha t} \]
\[ T_2 = \frac{\ln 2}{\alpha} \]
| Параметр | Обозначение | Значение |
|---|---|---|
| Скорость роста | \(\alpha\) | 0.3 |
| Начальная популяция | \(u_0\) | 1.0 |
| Время моделирования | \(t_{max}\) | 10.0 |
using DifferentialEquations, Plots, DataFrames
function exponential_growth!(du, u, p, t)
α = p
du[1] = α * u[1]
end
# Параметры
u0 = [1.0]
α = 0.3
tspan = (0.0, 10.0)
# Решение ОДУ
prob = ODEProblem(exponential_growth!, u0, tspan, α)
sol = solve(prob, Tsit5(), saveat=0.1)
# Создание DataFrame
df = DataFrame(t=sol.t, u=first.(sol.u))Базовая модель: α = 0.3
Первые 5 строк результатов:
Row │ t u
─────┼────────────────────
1 │ 0.0 1.0
2 │ 0.1 1.03045
3 │ 0.2 1.06184
4 │ 0.3 1.09417
5 │ 0.4 1.1275
Время удвоения: 2.31
param_grid = Dict(
:α => [0.1, 0.3, 0.5, 0.8, 1.0],
:u0 => [[1.0]],
:tspan => [(0.0, 10.0)]
)
all_params = dict_list(param_grid)
println("Всего комбинаций: ", length(all_params))function run_single_experiment(params::Dict)
@unpack u0, α, tspan = params
prob = ODEProblem(exponential_growth!, u0, tspan, (α=α,))
sol = solve(prob, Tsit5(), saveat=0.1)
doubling_time = log(2) / α
return Dict(
"time_points" => sol.t,
"population_values" => first.(sol.u),
"doubling_time" => doubling_time
)
endСравнение различных значений α
Наблюдения: - Чем больше α, тем быстрее рост - При α = 1.0 популяция растёт в ~2.7 раза быстрее, чем при α = 0.3 - Все кривые имеют экспоненциальный характер
Время удвоения
| α | Теоретическое \(T_2\) | Численное \(T_2\) | Погрешность |
|---|---|---|---|
| 0.1 | 6.93 | 6.93 | 0.0% |
| 0.3 | 2.31 | 2.31 | 0.0% |
| 0.5 | 1.39 | 1.39 | 0.0% |
| 0.8 | 0.87 | 0.87 | 0.0% |
| 1.0 | 0.69 | 0.69 | 0.0% |
using BenchmarkTools
for α_value in [0.1, 0.3, 0.5, 0.8, 1.0]
prob = ODEProblem(exponential_growth!, [1.0], (0.0, 10.0), α_value)
b = @benchmark solve($prob, Tsit5(), saveat=0.1) samples=100
println("α = $α_value: ", median(b).time/1e6, " ms")
endВремя вычисления
Вывод: Время вычисления практически не зависит от параметра α.
# Установка Jupyter через pipx
sudo apt install pipx -y
pipx ensurepath
source ~/.bashrc
pipx install jupyter
# Запуск
jupyter notebook --no-browser --ip=0.0.0.0Jupyter Notebook
---
title: "Лабораторная работа №1"
subtitle: "Модель экспоненциального роста"
author: "Алина Тарасова"
---
# Введение
# Теоретическое описание
# Модель экспоненциального роста
**Цель:** Исследовать решение уравнения $\frac{du}{dt} = \alpha u$.
Экспоненциальный рост — это процесс увеличения величины, при котором
скорость роста пропорциональна текущему значению [стр. 69].
## Инициализация проекта и загрузка пакетов
::: {#21d3a44c .cell}
``` {.julia .cell-code}
using DrWatson
@quickactivate "project"
using DifferentialEquations
using Plots
using DataFrames
using JLD2:::
Уравнение экспоненциального роста:
Зададим начальные параметры: - \(u_0 = [1.0]\) — начальная популяция - \(\alpha = 0.3\) — скорость роста - \(t \in [0, 10]\) — временной интервал
Создадим и решим задачу:
Построим график решения:
Сохраним график в папку plots:
Создадим таблицу с данными:
Вычислим время удвоения популяции: Время удвоения вычисляется по формуле \(T_2 = \ln(2)/\alpha\) [стр. 70].
Сохраним все данные для последующего анализа:
ИЗМЕНЕНИЕ: Добавлен DrWatson для управления проектом и параметрами
Установка каталогов
Модель: 𝑑𝑢/𝑑𝑡 = 𝛼 ⋅ 𝑢
именованный кортеж
ОСНОВНОЕ ИЗМЕНЕНИЕ: Все параметры собраны в Dict для
Базовый набор параметров (один эксперимент)
base_params = Dict(
:u0 => [1.0], # начальная популяция
:α => 0.3, # скорость роста
:tspan => (0.0, 10.0), # интервал времени:solver => Tsit5(), # метод решения
:saveat => 0.1, # шаг сохранения результатов
:experiment_name => "base_experiment"
)
println("Базовые параметры эксперимента:")
for (key, value) in base_params
println(" $key = $value")
endИСПРАВЛЕНИЕ: Возвращаем Dict со строковыми ключами
function run_single_experiment(params::Dict)
@unpack u0, α, tspan, solver, saveat = params
prob = ODEProblem(exponential_growth!, u0, tspan, (α=α,)) #
Создаем и решаем задачу
sol = solve(prob, solver; saveat=saveat)
final_population = last(sol.u)[1] # Анализ результатов
doubling_time = log(2) / α
return Dict(
"solution" => sol,
"time_points" => sol.t,
"population_values" => first.(sol.u),
"final_population" => final_population,
"doubling_time" => doubling_time,
"parameters" => params # Сохраняем исходные параметры
) # Используем строки как ключи для совместимости с DrWatson
endИЗМЕНЕНИЕ: Используем produce_or_load для автоматического
кэширования
data, path = produce_or_load(
datadir(script_name, "single"), # Папка для сохранения
base_params, # Параметры эксперимента
run_single_experiment, # Функция для выполнения
prefix = "exp_growth", # Префикс имени файла
tag = false, # Не добавлять git-тег
verbose = true
)
println("\nРезультаты базового эксперимента:")
println(" Финальная популяция: ", data["final_population"])
println(" Время удвоения: ", round(data["doubling_time"]; digits=2))
println(" Файл результатов: ", path)Сохраним график в папку plots
НОВАЯ СЕКЦИЯ: Исследование влияния параметра α Сетка параметров для сканирования
param_grid = Dict(
:u0 => [[1.0]], # фиксируем начальное условие
:α => [0.1, 0.3, 0.5, 0.8, 1.0], # исследуемые значения скорости
роста
:tspan => [(0.0, 10.0)], # фиксируем интервал времени
:solver => [Tsit5()], # фиксируем метод решения
:saveat => [0.1], # фиксируем шаг сохранения
:experiment_name => ["parametric_scan"]
)Генерация всех комбинаций параметров
НОВАЯ СЕКЦИЯ: Автоматический запуск и сохранение всех вариантов
all_results = []
all_dfs = []
for (i, params) in enumerate(all_params)
println("Прогресс: $i/$(length(all_params)) | α = $(params[:α])")
data, path = produce_or_load(
datadir(script_name, "parametric_scan"), # Данные
params, # Текущий набор параметров
run_single_experiment, # Функция для выполнения
prefix = "scan", # Префикс имени файла
tag = false,
verbose = false # Не выводить подробности для
каждого запуска
) # Автоматическое сохранение/загрузка каждого эксперимента
result_summary = merge(
params,
Dict(
:final_population => data["final_population"],
:doubling_time => data["doubling_time"],
:filepath => path # Путь к сохраненным данным
)
) # Сохраняем сводные результаты (используем символы для
параметров, но данные из data - строки)
push!(all_results, result_summary)
df = DataFrame(
t = data["time_points"],
u = data["population_values"],
α = fill(params[:α], length(data["time_points"]))
) # Сохраняем полные данные для визуализации
push!(all_dfs, df)
endНОВАЯ СЕКЦИЯ: Сравнительный анализ всех экспериментов Сводная таблица результатов
Сравнительный график всех траекторий
p2 = plot(size=(800, 500), dpi=150)
for params in all_params
data, _ = produce_or_load(
datadir(script_name, "parametric_scan"),
params,
run_single_experiment,
prefix = "scan"
) # Загружаем данные (они уже есть на диске)
plot!(p2, data["time_points"], data["population_values"],
label="α = $(params[:α])",
lw=2,
alpha=0.8
)
end
plot!(p2,
xlabel="Время, t",
ylabel="Популяция, u(t)",
title="Параметрическое исследование: влияние α на рост",
legend=:topleft,
grid=true
)Сохраним график в папку plots
График зависимости времени удвоения от α
Теоретическая кривая: t₂ = ln(2)/α
Сохраним график в папку plots
ИЗМЕНЕНИЕ: Бенчмаркинг для разных значений α
println("\n" * "="^60)
println("Бенчмаркинг для разных значений α")
println("="^60)
benchmark_results = []
for α_value in param_grid[:α]
bench_params = Dict(
:u0 => [1.0],
:α => α_value,
:tspan => (0.0, 10.0),
:solver => Tsit5(),
:saveat => 0.1
) # Подготавливаем параметры для бенчмарка
function benchmark_run() # Функция для бенчмарка
prob = ODEProblem(exponential_growth!,
bench_params[:u0],
bench_params[:tspan],
(α=bench_params[:α],))
return solve(prob, bench_params[:solver];
saveat=bench_params[:saveat])
end
println("\nБенчмарк для α = $α_value:")
b = @benchmark $benchmark_run() samples=100 evals=1 # Запуск
бенчмарка
push!(benchmark_results, (α=α_value, time=median(b).time/1e9)) #
время в секундах
println(" Среднее время: ", round(median(b).time/1e9;
digits=4), " сек")
endГрафик зависимости времени вычисления от α
Сохраним график в папку plots
НОВАЯ СЕКЦИЯ: Сохранение сводных данных для последующего
анализа
@save datadir(script_name, "all_results.jld2") base_params
param_grid all_params results_df bench_df
@save datadir(script_name, "all_plots.jld2") p1 p2 p3 p4
println("\n" * "="^60)
println("ЛАБОРАТОРНАЯ РАБОТА ЗАВЕРШЕНА")
println("="^60)
println("\nРезультаты сохранены в:")
println(" • data/$(script_name)/single/ - базовый
эксперимент")
println(" • data/$(script_name)/parametric_scan/ -
параметрическое сканирование")
println(" • data/$(script_name)/all_results.jld2 - сводные
данные")
println(" • plots/$(script_name)/ - все графики")
println(" • data/$(script_name)/all_plots.jld2 - объекты
графиков")
println("\nДля анализа результатов используйте:")
println(" using JLD2, DataFrames")
println(" @load \"data/$(script_name)/all_results.jld2\"")
println(" println(results_df)")
### Конфигурация `_quarto.yml`
```yaml
project:
title: "Отчёт по лабораторной работе"
author: "Алина Тарасова"
engine: julia
julia:
exeflags: ["--project=../labs/lab01/project"]
format:
html:
toc: true
code-fold: false
cd ~/work/study/2026-1/2026-1==study--simulation-modeling/report
quarto render report.qmd --to html
explorer.exe report.htmlГотовый отчёт
Git настроен и сконфигурирован
SSH и PGP ключи созданы и добавлены на GitHub
Git-flow инициализирован, создан первый релиз v1.0.0
Создано рабочее пространство по стандарту Denote
Julia и необходимые пакеты (30 минут установки)
Quarto для создания отчётов и презентаций
Jupyter для интерактивной работы
Инструменты для Conventional Commits
Базовая модель экспоненциального роста
Параметрическое исследование (5 значений α)
Бенчмаркинг производительности
Литературное программирование с Literate.jl
Jupyter notebooks Отчёт в Quarto (HTML) Презентация в формате reveal.js
Модель экспоненциального роста адекватно описывает процессы с постоянной скоростью роста и имеет простое аналитическое решение
Время удвоения обратно пропорционально скорости роста: \[ T_2 = \frac{\ln 2}{\alpha} \]
DrWatson.jl обеспечивает:
Literate.jl позволяет создавать самодокументируемый код, объединяя документацию и исполняемые скрипты
Quarto интегрирует код, результаты и текст в единый отчёт с возможностью экспорта в различные форматы
WSL Ubuntu предоставляет удобную среду для научных вычислений с доступом к инструментам Windows
tangle.jl для обновления отчётов при изменении кода| Инструмент | Версия | Назначение |
|---|---|---|
| Julia | 1.10.5 | Язык программирования |
| DifferentialEquations.jl | 7.12.0 | Решение ОДУ |
| Plots.jl | 1.40.0 | Визуализация |
| DrWatson.jl | 2.15.0 | Организация проектов |
| Literate.jl | 2.16.0 | Литературное программирование |
| Quarto | 1.6.42 | Создание отчётов и презентаций |
| Git | 2.43.0 | Контроль версий |
| Ubuntu | 22.04 LTS (WSL) | Операционная система |
# Создание новой функциональной ветки
git flow feature start <feature-name>
# Завершение работы над функцией
git flow feature finish <feature-name># Создание релиза
git flow release start <version>
standard-version
git flow release finish <version>---
## Author
author:
name: Алина Тарасова
degrees: студент
email: destinyshesaid@yandex.ru
affiliation:
- name: Российский университет дружбы народов
country: Российская Федерация
postal-code: 117198
city: Москва
address: ул. Миклухо-Маклая, д. 6
## Title
title: Лабораторная работа №1
subtitle: Подготовка стенда и модель экспоненциального роста
license: CC BY
date: today
date-format: "YYYY-MM-DD"
## Format
format:
revealjs:
theme: solarized
transition: slide
slide-number: true
width: 1200
height: 800
footer: "Имитационное моделирование | РУДН"
---